package com.nchu.commondevelopmentframework.common.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nchu.commondevelopmentframework.common.constant.ApiCodeConstant;
import com.nchu.commondevelopmentframework.common.domain.ApiResult;
import com.nchu.commondevelopmentframework.common.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

/**
 * @className: JwtAuthenticationFilter
 * @description: 自定义token验证过滤器，验证成功后将用户信息放入SecurityContext上下文
 * @author: Li Chuanwei
 * @date: 2024/02/07 20:18
 * @Company: Copyright [日期] by [作者或个人]
 **/
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private JwtUtils jwtUtils;

    public JwtAuthenticationFilter(JwtUtils jwtUtils) {
        this.jwtUtils = jwtUtils;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws  IOException {
        try {
            //获取请求头中的token
            String jwtToken = request.getHeader("token");
            String clientType = request.getHeader("Client-Type");

            if(!StringUtils.hasLength(clientType)){
                throw new RuntimeException("未携带设备类型");
            }

            //token不存在，交给其他过滤器处理
            if ((!StringUtils.hasLength(jwtToken))) {
                filterChain.doFilter(request, response);
                return;
            }

            //解析jwt令牌
            Claims claims;
            try {
                claims = jwtUtils.getClaims(jwtToken);
            } catch (Exception ex) {
                throw new RuntimeException("Token验证错误");
            }

            if(claims == null){
                throw new RuntimeException("Token验证错误");
            }

            if(!clientType.equals(claims.get("clientType"))){
                throw new RuntimeException("设备类型验证错误");
            }

            //获取用户信息
            String userid = claims.getSubject();
            String username = (String) claims.get("username");
            List<String> authorityString = (List<String>) claims.get("authorityString");

            // 将权限字符串列表转换为 GrantedAuthority 对象列表
            Collection<? extends GrantedAuthority> authorities = authorityString.stream()
                    .map(SimpleGrantedAuthority::new)
                    .toList();

            Authentication authentication = new UsernamePasswordAuthenticationToken(
                    username, null,
                    authorities);

            //将用户信息放入SecurityContext上下文
            SecurityContextHolder.getContext().setAuthentication(authentication);

            filterChain.doFilter(request, response);
        } catch (Exception ex) {
            //过滤器中抛出的异常无法被全局异常处理器捕获，直接返回错误结果
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json; charset=utf-8");
            String value = new ObjectMapper().writeValueAsString(ApiResult.fail(ApiCodeConstant.NOT_LOGIN,ex.getMessage()));
            response.getWriter().write(value);
        }
    }
}